#define USERPROG
#include "userprog/syscall.h"
#include <stdio.h>
#include <syscall-nr.h>
#include "threads/interrupt.h"
#include "threads/thread.h"
#include "threads/vaddr.h"
#include "userprog/process.h"
#include "devices/shutdown.h"

static void syscall_handler(struct intr_frame *);

void syscall_init(void) {
  intr_register_int(0x30, 3, INTR_ON, syscall_handler, "syscall");
}

static void syscall_handler(struct intr_frame *f) {
  uint32_t *args = (uint32_t *)f->esp;
  
  /* 验证指针有效性 */
  if (!is_user_vaddr(args) || !is_user_vaddr(f->esp)) {
    sys_exit(-1);
  }

  int syscall_number = args[0];
  
  switch (syscall_number) {
    case SYS_HALT:
      sys_halt();
      break;
    case SYS_EXIT:
      if (!is_user_vaddr(args + 1)) {
        sys_exit(-1);
      }
      sys_exit(args[1]);
      break;
    case SYS_EXEC:
      if (!is_user_vaddr(args + 1)) {
        sys_exit(-1);
      }
      f->eax = sys_exec((const char *)args[1]);
      break;
    default:
      printf("[ERROR] system call %d is unimplemented!\n", syscall_number);
      sys_exit(-1);
  }
}

/****************** 系统调用实现 ********************/
void sys_halt(void) {
  shutdown_power_off();
}

void sys_exit(int status) {
  struct thread *cur = thread_current();
  
  /* 只打印用户进程的退出信息 */
  if (cur->pcb != NULL && cur->pcb->cmdline != NULL) {
    printf("%s: exit(%d)\n", cur->pcb->cmdline, status);
  }
  
  thread_exit();
}

int sys_exec(const char *cmdline) {
  /* 验证指针有效性 */
  if (!is_user_vaddr(cmdline)) {
    return -1;
  }
  
  /* 复制用户空间字符串到内核空间 */
  char *kcmd = palloc_get_page(0);
  if (kcmd == NULL) {
    return -1;
  }
  
  if (strlcpy(kcmd, cmdline, PGSIZE) >= PGSIZE) {
    palloc_free_page(kcmd);
    return -1;
  }
  
  int pid = process_execute(kcmd);
  palloc_free_page(kcmd);
  return pid;
}